    <!DOCTYPE html>
<html lang="zh-cn">
	<head>
		<meta charset="utf-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
		<meta name="viewport" content="width=device-width, initial-scale=1">
		<meta name="author" content="nodejh">
		<meta name="description" content="My Blog">
		<meta name="generator" content="Hugo 0.31.1" />
		<title>从 Hexo 迁移到 Hugo &middot; nodejh</title>
		<link rel="shortcut icon" href="http://nodejh.com/images/favicon.ico">
		<link rel="stylesheet" href="http://nodejh.com/css/style.css">
		<link rel="stylesheet" href="http://nodejh.com/css/highlight.css">
		

		
		<link rel="stylesheet" href="http://nodejh.com/css/font-awesome.min.css">
		

		
		<link href="http://nodejh.com/index.xml" rel="alternate" type="application/rss+xml" title="nodejh" />
		
	</head>

    <body>
       <nav class="main-nav">
	
	
		<a href='http://nodejh.com/'> <span class="arrow">←</span>Home</a>
	
	<a href='http://nodejh.com/post'>Archive</a>
	<a href='http://nodejh.com/tags'>Tags</a>
	<a href='http://nodejh.com/projects'>Projects</a>
	<a href='http://nodejh.com/about'>About</a>

	

	
	<a class="cta" href="http://nodejh.com/index.xml">Subscribe</a>
	
</nav>


        <section id="wrapper" class="post">
            <article>
                <header>
                    <h1>
                        从 Hexo 迁移到 Hugo
                    </h1>
                    <h2 class="headline">
                    Sep 30, 2016 17:14
                    · 1343 words
                    · 3 minutes read
                      <span class="tags">
                      
                      
                          
                              <a href="http://nodejh.com/tags/hugo">hugo</a>
                          
                              <a href="http://nodejh.com/tags/hexo">hexo</a>
                          
                              <a href="http://nodejh.com/tags/blog">blog</a>
                          
                      
                      
                      </span>
                    </h2>
                </header>
                
                  
                    <div id="toc">
                      <nav id="TableOfContents">
<ul>
<li>
<ul>
<li><a href="#1-将-hexo-的-yaml-转换为-hugo-的-toml">1. 将 Hexo 的 YAML 转换为 Hugo 的 TOML</a></li>
<li><a href="#2-图片目录的迁移">2. 图片目录的迁移</a></li>
<li><a href="#3-主题">3. 主题</a></li>
<li><a href="#4-部署">4. 部署</a></li>
</ul></li>
</ul>
</nav>
                    </div>
                  
                
                <section id="post-body">
                    <p>把博客从 <a href="http://hexo.io/">Hexo</a> 迁移到了 <a href="http://gohugo.io/">Hugo</a>。主要原因有二：</p>

<p></p>

<ul>
<li>Hexo 中文乱码。当中文大概超过1000字，就出现奇怪的乱码。看了 Hexo 的 ISSUE，这个问题也不只我遇到。</li>
<li>Hexo 生成静态文件太慢了，等上十几二十秒是常有的事。</li>
</ul>

<p>遂弃用 Hexo。</p>

<h2 id="1-将-hexo-的-yaml-转换为-hugo-的-toml">1. 将 Hexo 的 YAML 转换为 Hugo 的 TOML</h2>

<p>Hugo 的配置文件是 TOML 格式的，其生成的 Markdown 文件的 front matter（不知如何翻译）也是 TOML 结构：</p>

<pre><code>+++
date = &quot;2016-09-30T17:14:37+08:00&quot;
description = &quot;&quot;
title = &quot;Migrate to Hugo from Hexo&quot;
tags = [&quot;hugo&quot;, &quot;hexo&quot;, &quot;blog&quot;]

+++
</code></pre>

<p>而 Hexo 的配置文件是 YAML 格式，其 Markdown 文件的 front matter 如下：</p>

<pre><code>title: 'Start React with Webpack'
date: 2016-09-09 04:11:13
tags:
  - webpack
  - react

---
</code></pre>

<p>所以直接将 Hexo 的 Markdown 文件复制到 Hugo 中是不行的，必须得转换一下格式。虽然 Hugo 也可以直接在 <code>config.toml</code> 中配置 <code>metaDataFormat:&quot;yaml&quot;</code>，这样 Hugo 就会生成 YAML 结构的 front matter ，但原 Hexo 的 Markdown 文件依旧不能正常的转换，因为 <code>date</code> 的格式不一样。</p>

<p>在 Hexo 中，文件里面的 <code>date: 2016-09-09 04:11:13</code> 并没有存储时区信息，而是把时区放在了 <code>_config.yml</code> 配置文件中。</p>

<p>By the way，TOML 是 GitHub 觉得 YAML 不够简洁优雅，所以捣鼓出来的一个东西。既然现在在用 Hugo，就没有理由不用 TOML 代替原来的 YAML。</p>

<p>其实两者之间的转换也很简单，我用 JS 写了一个脚本来将 YAML 转换为 TOML：</p>

<pre><code>// yaml_to_toml.js
const readline = require('readline');
const fs = require('fs');
const os = require('os');
const moment = require('moment-timezone');  // 需要通过 npm install moment-timezone 来安装


const timezone = 'Asia/Shanghai';  // 时区
const src = 'hexo';  // hexo .md 文件源目录
const target = 'post';  // 目标文件目录


// 开始转换
readDir();


// 遍历目录
function readDir() {
    // read all files in src
    fs.readdir(src, function(err, files) {
        files.map((filename) =&gt; {
            // get the file extension
            const extension = filename.substr(filename.lastIndexOf('.', filename.length));
            if (extension === '.md') {
              readFile(`${filename}`);
            }
        });
    });

}


function readFile(filename) {
  fs.readFile(`${src}/${filename}`, { encoding: 'utf8' }, function(err, data) {
      if (err) {
          return console.log('err: ', err);
      }

      const content = data.split('---');
      const head = content[0].split('\n');
      // console.log('head: ', head);

      let newHead = head.map((item, index) =&gt; {
        // console.log('slpitHead: ', slpitHead(item, index, head));
        return slpitHead(item, index, head);
      });
      newHead = newHead.filter((item) =&gt; {return item;});
      // console.log('newHead: ', newHead);
      const newContent = `+++${os.EOL}${newHead.join(os.EOL)}${os.EOL}${os.EOL}+++${os.EOL}${content[1]}`;
      fs.writeFile(`${target}/${filename}`, newContent, {
          encoding: 'utf8'
      }, function(err) {
          if (err) {
            throw err;
          }
          console.log(`${filename}  生成成功！`);
      });
  });
}



function slpitHead(item, index, head) {
  // title
  if (item.indexOf('title:') !== -1) {
    return `title = &quot;${item.split('title:')[1].trim()}&quot;`;
  }

  // date
  if (item.indexOf('date:') !== -1) {
    return `date = &quot;${(moment.tz(item.split('date:')[1], timezone)).format()}&quot;`;
  }

  // tags
  if (item.indexOf('tags:') !== -1) {
    // console.log('tags...');
    const tags = [];
    for (let i=index+1; i&lt;head.length; i++) {
      if (head[i].indexOf('-') !== -1) {
        // console.log('head[i].split('-')[1]: ', head[i].split('-')[1]);
        tags.push(head[i].split('-')[1].trim());
      } else {
        break;
      }
    }
    // console.log('tags: ', tags);
    return `tags = ${JSON.stringify(tags)}`;
  }

  // categories
  if (item.indexOf('categories:') !== -1) {
    const categories = [];
    for (let i=index+1; i&lt;head.length; i++) {
      if (head[i].indexOf('-') !== -1) {
        categories.push(head[i].split('-')[1].trim());
      } else {
        break;
      }
    }
    // console.log('categories: ', categories);
    return `categories = ${JSON.stringify(categories)}`;
  }

  return false;
}
</code></pre>

<p>先配置好 <code>timezone</code> <code>src</code> <code>target</code> 三个参数。然后 <code>npm install moment-timezone</code> 安装需要的第三方包，最后 <code>node yaml_to_toml.js</code> 即可。</p>

<h2 id="2-图片目录的迁移">2. 图片目录的迁移</h2>

<p>本地图片迁移也非常简单。</p>

<p>我之前使用 Hexo 的时候，是将所有图片都放在 <code>source/images/</code> 目录里面的，在 Markdown 文件中引入图片是这样的： <code>![image title](/iamges/image_name.png)</code>。</p>

<p>Hugo 的图片可以直接放在其 <code>static/</code> 目录里面，其路径就是 <code>/iamges/image_name.png</code>，所以我只需要将 Hexo 中的 <code>images</code> 目录复制到 Hugo 的 <code>static/</code> 目录下即可。</p>

<h2 id="3-主题">3. 主题</h2>

<p>看遍了 Hugo 给出的所有主题，都不满意。很多主题都超级简洁，这种风格还是很喜欢的。所以决定自己写一个。</p>

<p>最终 Fork 了 <a href="https://github.com/digitalcraftsman/hugo-cactus-theme">https://github.com/digitalcraftsman/hugo-cactus-theme</a> 这个主题，然后改成了自己想要的样子。</p>

<p>主页</p>

<p><img src="http://oh1ywjyqf.bkt.clouddn.com/blog/2016-11-22-Migrate-to-Hugo-from-Hexo-1.png" alt="Migrate-to-Hugo-from-Hexo-1.png" /></p>

<p>文章页</p>

<p><img src="http://oh1ywjyqf.bkt.clouddn.com/blog/2016-11-22-Migrate-to-Hugo-from-Hexo-2.png" alt="Migrate-to-Hugo-from-Hexo-2.png" /></p>

<p>改后的主题源码：<a href="https://github.com/nodejh/hugo-cactus-theme">https://github.com/nodejh/hugo-cactus-theme</a>。</p>

<h2 id="4-部署">4. 部署</h2>

<p>由于 Github Pages 国内访问速度慢，所以同时把静态页面部署到了 Github Page 和 Coding Pages。</p>

<pre><code>// 添加两个仓库
git remote add all https://github.com/nodejh/nodejh.github.io
git remote set-url origin --push --add https://git.coding.net/nodejh/nodejh.git
git remote set-url origin --push --add https://github.com/nodejh/nodejh.github.io
</code></pre>

<p>然后只需要执行 <code>git push all branch</code> 就可以同时向两个仓库 push 代码了。但暂时不这样做。而是在 <code>public</code> 目录外创建一个 <code>deploy.sh</code> 目录，用来自动部署：</p>

<pre><code>#!/bin/bash

echo -e &quot;\033[0;32mDeploying updates to GitHub...\033[0m&quot;

# Build the project.
hugo # if using a theme, replace by `hugo -t &lt;yourtheme&gt;`

# Go To Public folder
cd public
# Add changes to git.
git add -A

# Commit changes.
msg=&quot;rebuilding site `date`&quot;
if [ $# -eq 1 ]
  then msg=&quot;$1&quot;
fi
git commit -m &quot;$msg&quot;

# Push source and build repos.
git push origin master

# Come Back
cd ..
</code></pre>

<p>接下来再给 <code>deploy.sh</code> 添加可执行权限 <code>chmod +x deploy.sh</code>。然后每次写完东西只需要 <code>.／deploy.sh 'commit message'</code> 即可。</p>

<hr />

<p>Github Issue: <a href="https://github.com/nodejh/nodejh.github.io/issues/11">https://github.com/nodejh/nodejh.github.io/issues/11</a></p>
                </section>
            </article>

            

            
                <div id="disqus_thread"></div>
<script type="text/javascript">
    var disqus_shortname = 'nodejh'; 

     
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
</div>

            

            
                <ul id="post-list" class="archive readmore">
    <h3>Read more</h3>
    
    
        
        <li>
            <a href="http://nodejh.com/post/how-to-vertically-middle-align-floated-elements-with-flexbox/">使用 Flexbox 使浮动元素垂直居中<aside class="dates">Jul 28</aside></a>
        </li>
        
   
    
        
        <li>
            <a href="http://nodejh.com/post/css-responsive-navigation-menu/">纯 CSS 实现响应式导航菜单<aside class="dates">Jul 28</aside></a>
        </li>
        
   
    
        
        <li>
            <a href="http://nodejh.com/post/vue2-tutorials-02-todolist/">实现一个TodoList - Vue2 Tutorials (二)<aside class="dates">Jul 17</aside></a>
        </li>
        
   
    
        
        <li>
            <a href="http://nodejh.com/post/electron-quick-start/">Electron 快速入门<aside class="dates">Jul 6</aside></a>
        </li>
        
   
    
        
        <li>
            <a href="http://nodejh.com/post/vue2-tutorials-01-quick-start/">快速入门 - Vue2 Tutorials (一)<aside class="dates">Jul 6</aside></a>
        </li>
        
   
    
        
        <li>
            <a href="http://nodejh.com/post/project-documentation-with-hexo-static-site-generator/">使用 Hexo 创建项目文档网站<aside class="dates">Jul 5</aside></a>
        </li>
        
   
    
        
        <li>
            <a href="http://nodejh.com/post/handy-mysql-commands/">常用 MySQL 命令<aside class="dates">Mar 30</aside></a>
        </li>
        
   
    
        
        <li>
            <a href="http://nodejh.com/post/understand-the-oracle-startup-process/">深入理解 Oracle 启动原理<aside class="dates">Mar 26</aside></a>
        </li>
        
   
    
        
        <li>
            <a href="http://nodejh.com/post/setting-environmental-variables-in-macos/">macOS/Linux 环境变量设置<aside class="dates">Mar 19</aside></a>
        </li>
        
   
    
        
        <li>
            <a href="http://nodejh.com/post/how-to-create-auto-increment-column-in-oracle/">在 Oracle 中设置自增列<aside class="dates">Feb 20</aside></a>
        </li>
        
   
</ul>
            

            <footer id="footer">
    
        <div id="social">

	
	
    <a class="symbol" href="https://www.facebook.com/nodejh">
        <i class="fa fa-facebook-square"></i>
    </a>
    
    <a class="symbol" href="https://www.github.com/nodejh">
        <i class="fa fa-github-square"></i>
    </a>
    
    <a class="symbol" href="https://www.twitter.com/nodejh">
        <i class="fa fa-twitter-square"></i>
    </a>
    


</div>

    
    <p class="small">
    
       © Copyright 2017 <i class="fa fa-heart" aria-hidden="true"></i> nodejh
    
    </p>
    <p class="small">
        Powered by <a href="http://www.gohugo.io/">Hugo</a> Theme By <a href="https://github.com/nodejh/hugo-theme-cactus-plus">nodejh</a>
    </p>
</footer>

        </section>

        <script src="http://nodejh.com/js/jquery-2.2.4.min.js"></script>
<script src="http://nodejh.com/js/main.js"></script>
<script src="http://nodejh.com/js/highlight.min.js"></script>
<script>hljs.initHighlightingOnLoad();</script>




  
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

ga('create', 'UA-84989670-1', 'auto');
ga('send', 'pageview');
</script>




<script>
var baiduAnalytics = '39843ea392201290bd6f76173d2e1633';
var _hmt = _hmt || [];
(function() {
  var hm = document.createElement("script");
  hm.src = "https://hm.baidu.com/hm.js?" + baiduAnalytics;
  var s = document.getElementsByTagName("script")[0];
  s.parentNode.insertBefore(hm, s);
})();
</script>


    </body>
</html>
